﻿using DrawTools.Common;
using DrawTools.Utils;
using System;
using System.Windows;
using System.Windows.Media;

namespace DrawTools.Tools
{
    /// <summary>
    /// 像素比率设置
    /// </summary>
    public sealed class PixelRateDrawTool : DrawGeometryBase
    {
        #region 字段
        private Point? startPoint, endPoint;
        private Point center, textPoint, tangent1, tangent2;
        private double angle;
        public static Func<double> SetPixelRateAction { get; set; }
        #endregion 字段

        /// <summary>
        /// 像素比率设置
        /// </summary>
        /// <param name="drawingCanvas"></param>
        public PixelRateDrawTool(DrawingCanvas drawingCanvas) : base(drawingCanvas)
        {
            DrawingToolType = DrawToolType.Check;
            // 准备要处理的事件
            CanTouchDown = true;
        }

        protected override void OnDrawing(DrawingContext dc)
        {
            base.OnDrawing(dc);
            if (textPoint.X != 0 || textPoint.Y != 0)
            {
                var formattedText = GetFormattedText();
                var textGeometry = formattedText.BuildGeometry(textPoint);
                var transformGroup = new TransformGroup();
                transformGroup.Children.Add(new RotateTransform(angle, center.X, center.Y));
                transformGroup.Children.Add(geometry.Transform);
                textGeometry.Transform = transformGroup;
                dc.DrawGeometry(Pen.Brush, null, textGeometry);
            }
        }
        #region 鼠标键盘事件

        public override bool OnTouchLeave(Point point, bool isLeaved = false)
        {
            if (!endPoint.HasValue || (startPoint.Value - endPoint.Value).Length < Pen.Thickness)
            {
                drawingCanvas.DeleteVisual(this);
            }
            else
            {
                Draw();
            }
            drawingCanvas.DeleteWorkingDrawTool(this);
            IsFinish = true;
            CanKeyDown = false;
            CanTouchMove = true;
            CanTouchLeave = false;

            if (isLeaved || TouchId == 0 && drawingCanvas.IsMouseCaptured) drawingCanvas.ReleaseMouseCapture();

            if (startPoint != null)
            {
                var x = Math.Abs(point.X - startPoint.Value.X);
                var y = Math.Abs(point.Y - startPoint.Value.Y);
                var len = Math.Sqrt(x * x + y * y);
                double rate = 1;
                if (SetPixelRateAction != null)
                {
                    rate = SetPixelRateAction.Invoke();
                }
                else
                {
                    var win = new Common.SetPixelRateWindow();
                    if (win.ShowDialog() == true)
                    {
                        rate = win.Rate;
                    }
                }
                if (rate > 0)
                {
                    Dpi.PixelRate = len / rate;
                }
            }
            return true;
        }

        public override bool OnTouchDown(int touchId, Point point)
        {
            TouchId = touchId;
            if (!startPoint.HasValue)
            {
                drawingCanvas.AddWorkingDrawTool(this);
                startPoint = point;
                geometry = new PathGeometry();
                var figure = new PathFigure();
                pathGeometry.Figures.Add(figure);
                CanTouchMove = true;
                if (TouchId != 0 || !drawingCanvas.CaptureMouse()) CanTouchLeave = true;
                drawingCanvas.AddVisual(this);
                return true;
            }
            else
                return OnTouchLeave(point);
        }

        public override bool OnTouchMove(Point point)
        {
            var start = startPoint.Value;

            if ((start - point).Length < drawingCanvas.StrokeThickness) return true;

            var dc = RenderOpen();
            endPoint = point;
            var x = Math.Abs(point.X - start.X) / Dpi.Cm2Wpf;
            var y = Math.Abs(point.Y - start.Y) / Dpi.Cm2Wpf;
            var len = Math.Sqrt(x * x + y * y);
            Text = (len * 10).ToString("0.00") + "mm";

            center = new Point((start.X + point.X) / 2, (start.Y + point.Y) / 2);
            var width = Text.Length * FontSize / 2;     // 文字宽度
            textPoint = new Point(center.X - width / 2, center.Y - FontSize * 1.2 - Pen.Thickness);     // 文字左上角，1.2倍行高

            double? k = null;// 斜率

            if (start.X == point.X) angle = start.Y > point.Y ? 90 : -90;
            else
            {
                k = (point.Y - start.Y) / (point.X - start.X);
                angle = Math.Atan(k.Value) / Math.PI * 180;
            }
            var formattedText = GetFormattedText(Text);
            dc.PushTransform(new RotateTransform(angle, center.X, center.Y));
            dc.DrawText(formattedText, textPoint);
            dc.Pop();

            var tangentK = k.HasValue ? -1 / k : null;
            var tangentLen = Pen.Thickness + FontSize * 1.2;

            if (tangentK.HasValue)
            {
                var offsetX1 = Math.Sqrt(tangentLen * tangentLen / (1 + tangentK.Value * tangentK.Value)) * (angle > 0 ? 1 : -1);

                tangent1.X = offsetX1 + start.X;
                tangent1.Y = start.Y + offsetX1 * tangentK.Value;

                tangent2.X = offsetX1 + point.X;
                tangent2.Y = point.Y + offsetX1 * tangentK.Value;
            }
            else
            {
                tangent1.X = start.X + (angle == 90 ? tangentLen : -tangentLen);
                tangent1.Y = start.Y;

                tangent2.X = point.X + (angle == 90 ? tangentLen : -tangentLen);
                tangent2.Y = point.Y;
            }

            var figure = pathGeometry.Figures[0];
            figure.StartPoint = tangent1;
            figure.Segments.Clear();

            var line = new LineSegment(start, IsStroked) { IsSmoothJoin = true };
            figure.Segments.Add(line);
            line = new LineSegment(point, IsStroked) { IsSmoothJoin = true };
            figure.Segments.Add(line);
            line = new LineSegment(tangent2, IsStroked) { IsSmoothJoin = true };
            figure.Segments.Add(line);

            dc.DrawGeometry(null, Pen, geometry);
            dc.Close();

            return true;
        }

        #endregion 鼠标键盘事件
    }
}